<?php

namespace common\service;


use common\exception\LogicException;
use common\model\ProjectDelayReviewWorkflowRelationModel;
use common\model\ProjectStepReviewWorkflowRelationModel;
use common\model\UserModel;
use support\ErrorCode;
use think\Exception;

/**
 * 内部审核工作流服务
 */
class DelayOrderTaskReviewWorkflowService extends ReviewWorkflowService
{
    /**
     * 查询审核流配置
     * @param $projectId
     * @param $stepCategoryId
     * @return mixed
     */
    public function getProjectTemplateReviewWorkFlowConfig($projectId, $stepCategoryId)
    {
        $project = ProjectService::getInstance()->getProject($projectId, '*', true);
        $projectTemplateStepCategoryConfig = TemplateService::getInstance()->findStepCategoryConfig(['filter' => ['id' => $project['project_template_id']]]);
        $projectTemplateStepCategoryConfig = array_column($projectTemplateStepCategoryConfig, 'delay_order_task_review_workflow_id', 'id');

        if (empty($projectTemplateStepCategoryConfig) || !isset($projectTemplateStepCategoryConfig[$stepCategoryId]) || $projectTemplateStepCategoryConfig[$stepCategoryId] <= 0) {
            return 0;
        }
        return $projectTemplateStepCategoryConfig[$stepCategoryId];
    }

    /**
     * 查询任务审批流
     * @param int $projectId
     * @param int $stepCategoryId
     * @param int $userId
     * @return array
     * @throws Exception
     */
    public function selectReview(int $projectId, int $stepCategoryId, int $userId): array
    {
        /**
         * 延期任务审核流匹配用户
         * 1. 查询项目配置
         * 1.2 不存在 查询项目模板配置
         * 2. 查询出租户里的这些角色成员信息
         * 3. 进行特定规则匹配
         */

        // todo 从项目获取审核配置 在来检测项目模板是否有配置
        $projectReviewWorkflowRelation = $this->getProjectStepCategoryReviewWorkflow($projectId, $stepCategoryId);
        // 项目模板审核配置
        $projectTemplateReviewWorkflowId = $this->getProjectTemplateReviewWorkFlowConfig($projectId, $stepCategoryId);
        if (empty($projectReviewWorkflowRelation) || $projectReviewWorkflowRelation['review_workflow_id'] <= 0) {
            if (empty($projectTemplateReviewWorkflowId)) {
                throw new LogicException('missing delay order stepCategory review workflow config', ErrorCode::MISSING_DELAY_ORDER_STEP_CATEGORY_REVIEW_WORKFLOW_CONFIG);
            }
            $reviewWorkflowId = $projectTemplateReviewWorkflowId;
        } else {
            $reviewWorkflowId = $projectReviewWorkflowRelation['review_workflow_id'];
        }
        // 任务审核流配置信息
        //审批流查询
        $reviewFilter = [
            'id' => $reviewWorkflowId,
            'active' => "yes",
            'is_deleted' => "no",
        ];
        list($nodesData, $promoter, $reviewers,) = $this->getParsedWorkflow($reviewFilter);
        // 自己的用户信息
        $userInfo = teamones_request('teamones-im', 'user/get_my_user_info', null)['data'];
        // 组装部门id列表 把任务的部门id放在数组开头
        $myDepartmentInfoList = $userInfo['department_info'] ?? [];
        // 任务环节(工序分类)所包含的部门id 数组
        $headmanDepartmentIdList = array_column(array_filter($myDepartmentInfoList, function ($item) use ($stepCategoryId) {
            $stepCategoryIdList = explode(',', $item['step_category_ids']);
            return in_array($stepCategoryId, $stepCategoryIdList);
        }), 'id');
        $departmentIdList = array_column($myDepartmentInfoList, 'id');
        $departmentIdList = array_unique($departmentIdList);

        // 审核流需要的角色列表查询
        $reviewerRoles = array_column($reviewers, 'role');
        $roleListFilter = ["param" => [
            "filter" => [
                "role.code" => ['-in', implode(',', $reviewerRoles)]
            ],
            "fields" => "role.id,role.name,role.code"
        ]];
        $roleInfo = teamones_request('teamones-im', 'role/select', $roleListFilter)['data'];
        $roleInfo = $roleInfo['rows'] ?? [];
        if (empty($roleInfo)) {
            throw new LogicException("has not enough users to execute step check workflow", ErrorCode::NOT_ENOUGH_USERS_TO_EXECUTE_STEP_CHECK_WORKFLOW);
        }
        $roleNameMap = array_column($roleInfo, 'name', 'code');
        $reviewersData = [];
        $leftReviewerRoles = $reviewerRoles;
        $reviewerSearchedIndex = -1;
        $users = [];
        // 远端获取租户用户和角色信息
        if (!empty($leftReviewerRoles)) {
            $remoteUserListFilter = [
                "param" => [
                    "filter" => [
                        "role.code" => ["-in", implode(',', $leftReviewerRoles)]
                    ],
                    "fields" => "id,user_id,role_id,tenant_id,department_id,role.name as role_name,role.code as role_code,department.step_category_ids",
                    "page" => [1, C("database.database_max_select_rows")]
                ]
            ];

            $users = TenantService::getInstance()->selectTenantUser($remoteUserListFilter);
            if (empty($users)) {
                throw new LogicException("has not enough users to execute step check workflow", ErrorCode::NOT_ENOUGH_USERS_TO_EXECUTE_STEP_CHECK_WORKFLOW);
            }
        }
        //通过部门分组用户
        $usersGroupByDepartment = [];
        foreach ($users as $userIndex => &$user) {
            $user['role_code'] = [];
            if (!empty($user['role_info'])) {
                $user['role_code'] = array_column($user['role_info'], 'code');
            }
            foreach ($user['department_info'] as $department) {
                $usersGroupByDepartment[$department['id']][] = $users[$userIndex];
            }
        }
        $extraUserIdList = [$userId => $userId];
        $userQueryFields = 'id,name,avatar,phone,email';
        $reviewPreSetConfig = $projectReviewWorkflowRelation['review_node_config'] ?? [];
        if (count($reviewPreSetConfig) > 0) {
            $reviewPreSetConfigUserIdList = array_column($reviewPreSetConfig, 'user_id', 'user_id');
            $reviewPreSetConfig = array_column($reviewPreSetConfig, 'user_id', 'role_code');
            $extraUserIdList += $reviewPreSetConfigUserIdList;
        }
        $extraUserList = [];
        if (count($extraUserIdList)) {
            $extraUserList = model(UserModel::class)->where(['id' => ['IN', array_values($extraUserIdList)]])->field($userQueryFields)->select();
            $extraUserList = array_column($extraUserList, null, 'id');
        }
        $myself = $extraUserList[$userId];
        foreach ($reviewerRoles as $roleIndex => $role) {
            $tmpReviewerData = [
                'role_name' => $roleNameMap[$role],
                "role_code" => $role,
                "user_info" => [
                ],
                "skip" => 0,
                'user_id' => 0,
            ];
            $presetUserId = $reviewPreSetConfig[$role] ?? 0;
            // 如果角色匹配的时候 跳过了当前角色 就设置审核人为当前用户 自动跳过
            if ($roleIndex <= $reviewerSearchedIndex) {
                REVIEW_SKIP:
                $tmpReviewerData['user_info'][] = $myself;
                $tmpReviewerData['skip'] = 1;
                // 自动跳过能跳过的节点 不需要匹配u用户  直接使用saas user
                $reviewersData[] = $tmpReviewerData;
                continue;
            }

            // 配置了指定的人员去审核
            if ($presetUserId > 0 && isset($extraUserList[$presetUserId])) {
                // 如果当前角色code为组长 而且配置的人员 是我自己就跳过审核
                if ($role === TaskService::HEADMAN_CODE && $presetUserId == $userId) {
                    goto REVIEW_SKIP;
                }
                $tmpReviewerData['user_info'][] = $extraUserList[$presetUserId];
                $reviewersData[] = $tmpReviewerData;
                continue;
            }

            $reviewerUsers = [];
            //处理特殊情况
            switch ($role) {
                case TaskService::HEADMAN_CODE:
                    APP_DEBUG && trace("开始在我所在的部门里寻找组长角色用户", 'DEBUG');
                    // 用map存储用户信息 根据user_id进行索引去重
                    $tmpUsersMap = [];
                    foreach ($headmanDepartmentIdList as $departmentId) {
                        array_map(function ($item) use ($role, &$tmpUsersMap) {
                            if (in_array($role, $item['role_code'])) {
                                $tmpUsersMap[$item['user_id']] = $item;
                            }
                        }, $usersGroupByDepartment[$departmentId] ?? []);
                    }
                    // 重新索引array 移除key
                    if (!empty($tmpUsersMap)) {
                        $reviewerUsers = array_values($tmpUsersMap);
                    } else {
                        //查不到用户 就从租户里查
                        APP_DEBUG && trace("[default] 开始在公司所有人里寻找{$role}角色用户", 'DEBUG');
                        $reviewerUsers = array_filter($users, function ($item) use ($role) {
                            return in_array($role, $item['role_code']);
                        });
                    }
                    break;
                case TaskService::PRODUCER_CODE:
                    //制片人  直接找制片人
                    APP_DEBUG && trace("开始全公司里寻找制片角色用户", 'DEBUG');
                    $reviewerUsers = array_filter($users, function ($item) use ($role) {
                        return in_array($role, $item['role_code']);
                    });
                    break;
                case TaskService::DIRECTOR_CODE:
                    // 导演 从租户里查
                    $reviewerUsers = array_filter($users, function ($item) use ($role) {
                        return in_array($role, $item['role_code']);
                    });
                    break;
                case TaskService::QA_CODE:
                case TaskService::ARTILIST_CODE:
                    //艺术家或者其他角色 直接进默认
                default:
                    // 默认处理 优先检查剧集分配数据 中是否包含
                    APP_DEBUG && trace("[default] 开始在我所在的部门里寻找{$role}角色用户", 'DEBUG');
                    //优先从本部门查  然后在租户里查
                    foreach ($departmentIdList as $departmentId) {
                        $reviewerUsers = array_filter($usersGroupByDepartment[$departmentId] ?? [], function ($item) use ($role) {
                            return in_array($role, $item['role_code']);
                        });
                    }

                    if (empty($reviewerUsers)) {
                        //查不到用户 就从租户里查
                        APP_DEBUG && trace("[default] 开始在公司所有人里寻找{$role}角色用户", 'DEBUG');
                        $reviewerUsers = array_filter($users, function ($item) use ($role) {
                            return in_array($role, $item['role_code']);
                        });
                    }
            }
            if (count($reviewerUsers) == 0) {
                APP_DEBUG && trace("没有匹配到{$role}角色用户", 'DEBUG');
                throw new LogicException("can`t found a {$role}", ErrorCode::ROLE_NOT_FOUND);
            } else if (count($reviewerUsers) === 1) {
                $tmpReviewerData['user_info'][] = array_shift($reviewerUsers)['saas_user'];
            } else {
                $reviewerUsers = array_column($reviewerUsers, null, 'user_id');
                $tmpReviewerData['user_info'] = array_column($reviewerUsers, 'saas_user');
            }
            $reviewersData[] = $tmpReviewerData;
        }
        return [
            "review_workflow" => $nodesData,
            "matched_data" => [
                'promoter' => $promoter,
                'reviewers' => $reviewersData,
                'self_info' => $userInfo,
            ],
        ];
    }

    /**
     * 查询项目环节审核流配置
     * @param int $projectId
     * @param int $stepCategoryId
     * @return null
     */
    private function getProjectStepCategoryReviewWorkflow(int $projectId, int $stepCategoryId)
    {
        $projectReviewWorkflowRelation = model(ProjectDelayReviewWorkflowRelationModel::class)->where(['project_id' => $projectId, 'step_category_id' => $stepCategoryId])->find();
        if (!empty($projectReviewWorkflowRelation)) {
            return CommonService::getFormatAttrData(model(ProjectStepReviewWorkflowRelationModel::class), $projectReviewWorkflowRelation);
        }
        return $projectReviewWorkflowRelation;
    }
}
